package cn.com.ctcloud.microservice.dynamicds.database.druid;

import java.sql.SQLException;
import java.util.Arrays;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.alibaba.druid.filter.logging.Slf4jLogFilter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * Title: 核心类库
 * <p>
 * Description: 配置Druid
 * <p>
 * Copyright: Copyright (c) 2008
 * <p>
 * Company: Liaoning Open Data Communication Co.,Ltd.
 *
 * @author lihui
 * @version 1.0.0
 */
@Data
@Slf4j
@Configuration
public class DruidDBConfig {
	@Value("${spring.datasource.druid.dbtype:mysql}")
	private String dbType;

	@Value("${spring.datasource.druid.package:null}}")
	private String typeAliasesPackage;

	@Value("${spring.datasource.druid.url:null}")
	private String dbUrl;

	@Value("${spring.datasource.druid.username:null}")
	private String username;

	@Value("${spring.datasource.druid.password:null}")
	private String password;

	@Value("${spring.datasource.driverClassName:null}")
	private String driverClassName;

	@Value("${spring.datasource.druid.initialSize:2}")
	private int initialSize;

	@Value("${spring.datasource.druid.minIdle:5}")
	private int minIdle;

	@Value("${spring.datasource.druid.maxActive:10}")
	private int maxActive;

	@Value("${spring.datasource.druid.maxWait:60000}")
	private int maxWait;

	@Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis:60000}")
	private int timeBetweenEvictionRunsMillis;

	@Value("${spring.datasource.druid.minEvictableIdleTimeMillis:300000}")
	private int minEvictableIdleTimeMillis;

	@Value("${spring.datasource.druid.validationQuery:null}")
	private String validationQuery;

	@Value("${spring.datasource.druid.testWhileIdle:false}")
	private boolean testWhileIdle;

	@Value("${spring.datasource.druid.testOnBorrow:false}")
	private boolean testOnBorrow;

	@Value("${spring.datasource.druid.testOnReturn:false}")
	private boolean testOnReturn;

	@Value("${spring.datasource.druid.filters:null}")
	private String filters;

	@Value("${spring.datasource.druid.filter.stat.log-slow-sql:false}")
	private boolean logslowSql;

	@Value("${spring.datasource.druid.filter.stat.merge-sql:false}")
	private boolean mergeSql;

	@Value("${spring.datasource.druid.filter.stat.slow-sql-millis:1000}")
	private long slowSqlMill;

	@Value("${spring.datasource.druid.pool-prepared-statements:false}")
	private boolean poolPreparedStatements;

	@Value("${spring.datasource.druid.max-pool-prepared-statement-per-connection-size:20}")
	private int maxPoolPreparedStatementPerConnectionSize;

	/**
	 * @Bean 声明，DataSource 对象为 Spring 容器所管理;
	 * @Primary 表示这里定义的DataSource将覆盖其他来源的DataSource。 StatFilter，用于统计监控信息。StatFilter的别名是stat。
	 *          统计SQL信息，合并统计。mergeStat是的MergeStatFilter缩写。 通过 DataSource
	 *          的属性<property name="filters" value="mergeStat" /> 或者 connectProperties属性来打开mergeSql功能
	 *          <property name="connectionProperties" value="druid.stat.mergeSql=true" />
	 *          StatFilter属性slowSqlMillis用来配置SQL慢的标准
	 * @return
	 */
	@Bean
	@Primary
	public DataSource dataSource() {
		final DruidDataSource datasource = new DruidDataSource();
		datasource.setUrl(dbUrl);
		datasource.setDriverClassName(driverClassName);
		datasource.setUsername(username);
		datasource.setPassword(password);

		//configuration
		datasource.setInitialSize(initialSize);
		datasource.setMinIdle(minIdle);
		datasource.setMaxActive(maxActive);
		datasource.setMaxWait(maxWait);
		datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
		datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
		datasource.setValidationQuery(validationQuery);
		datasource.setTestWhileIdle(testWhileIdle);
		datasource.setTestOnBorrow(testOnBorrow);
		datasource.setTestOnReturn(testOnReturn);
		datasource.setPoolPreparedStatements(poolPreparedStatements);
		datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
		try {
			/**
			 * 设置StatFilter，用于统计监控信息。 StatFilter的别名是stat
			 */
			datasource.setFilters(filters);
		} catch (final SQLException e) {
			log.error("druid configuration initialization filter : {0}", e);
		}
		datasource.setProxyFilters(Arrays.asList(statFilter(), logFilter()));
		return datasource;
	}

	@Bean
	@Primary
	public StatFilter statFilter() {
		final StatFilter statFilter = new StatFilter();
		statFilter.setSlowSqlMillis(slowSqlMill);
		statFilter.setLogSlowSql(logslowSql);
		statFilter.setMergeSql(mergeSql);
		return statFilter;
	}

	@Bean
	public Slf4jLogFilter logFilter() {
		final Slf4jLogFilter filter = new Slf4jLogFilter();
		//        filter.setResultSetLogEnabled(false);
		//        filter.setConnectionLogEnabled(false);
		//        filter.setStatementParameterClearLogEnable(false);
		//        filter.setStatementCreateAfterLogEnabled(false);
		//        filter.setStatementCloseAfterLogEnabled(false);
		//        filter.setStatementParameterSetLogEnabled(false);
		//        filter.setStatementPrepareAfterLogEnabled(false);
		return filter;
	}

	/**
	 * 创建数据源
	 *
	 * @param driverClass
	 *            驱动
	 * @param jdbcUrl
	 *            URL
	 * @param username
	 *            用户名
	 * @param password
	 *            密码
	 * @return 数据源
	 */
	public DataSource createDataSource(final String driverClass, final String jdbcUrl, final String username,
			final String password) {
		final DruidDataSource datasource = new DruidDataSource();
		datasource.setUrl(jdbcUrl);
		datasource.setDriverClassName(driverClass);
		datasource.setUsername(username);
		datasource.setPassword(password);

		//configuration
		datasource.setInitialSize(initialSize);
		datasource.setMinIdle(minIdle);
		datasource.setMaxActive(maxActive);
		datasource.setMaxWait(maxWait);
		datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
		datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
		datasource.setValidationQuery(validationQuery);
		datasource.setTestWhileIdle(testWhileIdle);
		datasource.setTestOnBorrow(testOnBorrow);
		datasource.setTestOnReturn(testOnReturn);
		datasource.setPoolPreparedStatements(poolPreparedStatements);
		datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
		try {
			/**
			 * 设置StatFilter，用于统计监控信息。 StatFilter的别名是stat
			 */
			datasource.setFilters(filters);
		} catch (final SQLException e) {
			log.error("druid configuration initialization filter : {0}", e);
		}
		datasource.setProxyFilters(Arrays.asList(statFilter(), logFilter()));

		log.debug("---创建数据源: jdbcUrl = " + jdbcUrl + " username = " + username);

		return datasource;
	}

}